﻿// ----------------------------------------------------------------------------------
// Microsoft Developer & Platform Evangelism
// 
// Copyright (c) Microsoft Corporation. All rights reserved.
// 
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// ----------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
// ----------------------------------------------------------------------------------

namespace umbraco.ACSExtensions
{
    using System;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.Text;
    using System.Xml;

    public class FederationConfiguationManager
    {
        private static string PrefixedSeparator = "/fed:";

        private readonly string configurationFileLocation;
        private XmlDocument document;
        private XmlNamespaceManager namespaceManager;

        public FederationConfiguationManager(string configurationFileLocation)
        {
            this.configurationFileLocation = configurationFileLocation;
            this.document = new XmlDocument();
            this.document.Load(this.configurationFileLocation);
            this.namespaceManager = new XmlNamespaceManager(this.document.NameTable);
            this.namespaceManager.AddNamespace("fed", this.document.DocumentElement.NamespaceURI);
        }

        public static string GetServiceXPath(string serviceName)
        {
            if (string.IsNullOrEmpty(serviceName))
            {
                return "/fed:configuration/fed:microsoft.identityModel/fed:service[count(@name)=0 or @name='']";
            }

            return GetFormattedXPath("/fed:configuration/fed:microsoft.identityModel/fed:service[@name and @name='{0}']", new string[] { serviceName });
        }

        public static string GetFormattedXPath(string xPath, params string[] args)
        {
            if (args == null)
            {
                args = new string[1];
            }

            if (string.IsNullOrEmpty(xPath))
            {
                throw new ArgumentNullException("xPath");
            }

            int startIndex = -1;
            int num2 = -1;
            int num3 = -1;
            int num4 = -1;
            int num5 = 0;
            string attributeName = null;
            string oldValue = null;
            string[] strArray2 = args;

            for (int i = 0; i < strArray2.Length; i++)
            {
                if (strArray2[i] == null)
                {
                    startIndex = xPath.IndexOf("[", num5, (int)(xPath.Length - num5));
                    num2 = xPath.IndexOf("]", startIndex + 1, (int)((xPath.Length - startIndex) - 1));
                    num3 = xPath.IndexOf("@", startIndex, (int)((xPath.Length - startIndex) - 1));
                    num4 = xPath.IndexOfAny(new char[] { ' ', '=' }, num3, (xPath.Length - num3) - 1);
                    attributeName = xPath.Substring(num3, num4 - num3);
                    oldValue = xPath.Substring(startIndex, (num2 - startIndex) + 1);
                    xPath = xPath.Replace(oldValue, GetDefaultAttributeXPath(attributeName));
                    num5 = num2;
                }
            }

            return string.Format(CultureInfo.InvariantCulture, xPath, args);
        }

        public XmlNode ReadIdfxConfigurationSectionNode()
        {
            return this.SelectSingleNodeFromDocument("/fed:configuration/fed:configSections/fed:section[@name and @name='microsoft.identityModel']");
        }

        public void WriteIdfxConfigurationSectionNode()
        {
            XmlElement newChild = this.CreateElementFromDocument("section");
            newChild.SetAttribute("name", "microsoft.identityModel");
            newChild.SetAttribute("type", "Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
            
            this.WriteXPathNodes("/fed:configuration/fed:configSections").AppendChild(newChild);
            
            XmlNode oldChild = this.SelectSingleNodeFromDocument("/fed:configuration/fed:configSections");
            
            if (oldChild != this.document.DocumentElement.FirstChild)
            {
                this.document.DocumentElement.RemoveChild(oldChild);
                this.document.DocumentElement.InsertAfter(oldChild, null);
            }
        }

        public XmlElement ReadHttpRuntime()
        {
            return (this.SelectSingleNodeFromDocument("/fed:configuration/fed:system.web/fed:httpRuntime") as XmlElement);
        }

        public void WriteHttpRuntimeRequestValidationMode(string requestValidatorType)
        {
            if (string.IsNullOrEmpty(requestValidatorType))
            {
                throw new ArgumentNullException("requestValidatorType");
            }

            XmlElement newChild = this.ReadHttpRuntime();
            if (newChild == null)
            {
                newChild = this.CreateElementFromDocument("httpRuntime");
                newChild.SetAttribute("requestValidationType", requestValidatorType);
                this.WriteXPathNodes("/fed:configuration/fed:system.web").InsertAfter(newChild, null);
            }
            else
            {
                newChild.SetAttribute("requestValidationType", requestValidatorType);
            }
        }

        public XmlNode ReadWebServerWSFederationAuthenticationModuleNode(string moduleName)
        {
            return this.SelectSingleNodeFromDocument(
                string.Format(
                    CultureInfo.InvariantCulture,
                    "/fed:configuration/fed:system.webServer/fed:modules/fed:add[@name and @name='{0}']",
                    moduleName));
        }

        public void WriteWebServerWSFederationAuthenticationModuleNode(string moduleName, string moduleType)
        {
            if (string.IsNullOrEmpty(moduleType))
            {
                throw new ArgumentNullException("moduleType");
            }

            XmlElement newChild = this.CreateElementFromDocument("add");
            newChild.SetAttribute("name", moduleName);
            newChild.SetAttribute("type", moduleType);
            newChild.SetAttribute("preCondition", "managedHandler");
            
            this.WriteXPathNodes("/fed:configuration/fed:system.webServer/fed:modules").AppendChild(newChild);
        }

        public XmlNode ReadWebServerSessionAuthenticationModuleNode()
        {
            return this.SelectSingleNodeFromDocument("/fed:configuration/fed:system.webServer/fed:modules/fed:add[@name and @name='SessionAuthenticationModule']");
        }

        public void WriteWebServerSessionAuthenticationModuleNode()
        {
            XmlElement newChild = this.CreateElementFromDocument("add");
            newChild.SetAttribute("name", "SessionAuthenticationModule");
            newChild.SetAttribute("type", "Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
            newChild.SetAttribute("preCondition", "managedHandler");
            
            this.WriteXPathNodes("/fed:configuration/fed:system.webServer/fed:modules").AppendChild(newChild);
        }

        public XmlNode ReadWebServerCustomModuleNode(string moduleName)
        {
            return this.SelectSingleNodeFromDocument(
                string.Format(
                    CultureInfo.InvariantCulture,
                    "/fed:configuration/fed:system.webServer/fed:modules/fed:add[@name and @name='{0}']",
                    moduleName));
        }

        public void WriteWebServerCustomModuleNode(string moduleName, string moduleType)
        {
            if (string.IsNullOrEmpty(moduleType))
            {
                throw new ArgumentNullException("moduleType");
            }

            XmlElement newChild = this.CreateElementFromDocument("add");
            newChild.SetAttribute("name", moduleName);
            newChild.SetAttribute("type", moduleType);
            newChild.SetAttribute("preCondition", "managedHandler");

            this.WriteXPathNodes("/fed:configuration/fed:system.webServer/fed:modules").AppendChild(newChild);
        }

        public XmlNode ReadLocationAuthorization(string locationPath)
        {
            return this.SelectSingleNodeFromDocument(
               string.Format(
                   CultureInfo.InvariantCulture,
                   "/fed:configuration/fed:location[@path and @path='{0}']",
                   locationPath));
        }

        public void WriteLocationAuthorization(string locationPath)
        {
            XmlElement newChild = this.CreateElementFromDocument("location");
            newChild.SetAttribute("path", locationPath);
            XmlElement element2 = this.CreateElementFromDocument("system.web");
            XmlElement element3 = this.CreateElementFromDocument("httpRuntime");
            XmlElement element4 = this.CreateElementFromDocument("pages");

            element3.SetAttribute("requestValidationMode", "2.0");
            element4.SetAttribute("validateRequest", "false");

            element2.AppendChild(element3);
            element2.AppendChild(element4);

            newChild.AppendChild(element2);
            
            this.WriteXPathNodes("/fed:configuration").InsertBefore(newChild, this.WriteXPathNodes("/fed:configuration/fed:system.web"));
        }

        public FederatedAuthenticationElement ReadFederatedAuthentication()
        {
            if (this.SelectSingleNodeFromDocument("/fed:configuration/fed:microsoft.identityModel/fed:service[count(@name)=0 or @name='']/fed:federatedAuthentication") != null)
            {
                var element = new FederatedAuthenticationElement(this.ReadWSFederation());
                element.CookieHandler = (XmlElement)this.SelectSingleNodeFromDocument("/fed:configuration/fed:microsoft.identityModel/fed:service[count(@name)=0 or @name='']/fed:federatedAuthentication/fed:cookieHandler");
                
                return element;
            }

            return null;
        }

        public void WriteFederatedAuthentication(FederatedAuthenticationElement federatedAuthenticationElement)
        {
            if (federatedAuthenticationElement == null)
            {
                throw new ArgumentNullException("federatedAuthenticationElement");
            }

            XmlElement newChild = this.CreateElementFromDocument("federatedAuthentication");
            this.WriteXPathNodes("/fed:configuration/fed:microsoft.identityModel/fed:service[count(@name)=0 or @name='']").AppendChild(newChild);
            
            if (federatedAuthenticationElement.WSFederation != null)
            {
                this.WriteWSFederation(federatedAuthenticationElement.WSFederation);
            }
            
            if (federatedAuthenticationElement.CookieHandler != null)
            {
                newChild.AppendChild(federatedAuthenticationElement.CookieHandler);
            }
        }

        public void UpdateCookieHandlerRequireSsl(FederatedAuthenticationElement federatedAuthenticationElement, bool requireSsl)
        {
            if (federatedAuthenticationElement.CookieHandler != null)
            {
                XmlAttribute namedItem = (XmlAttribute)federatedAuthenticationElement.CookieHandler.Attributes.GetNamedItem("requireSsl");
                
                if (namedItem != null)
                {
                    namedItem.Value = XmlConvert.ToString(requireSsl);
                }
                else
                {
                    federatedAuthenticationElement.CookieHandler.SetAttribute("requireSsl", XmlConvert.ToString(requireSsl));
                }
            }
            else
            {
                federatedAuthenticationElement.CookieHandler = this.CreateElementFromDocument("cookieHandler");
                federatedAuthenticationElement.CookieHandler.SetAttribute("requireSsl", XmlConvert.ToString(requireSsl));
            }
        }

        public IssuerNameRegistryElement ReadIssuerNameRegistry(string serviceName)
        {
            XmlNode node = this.SelectSingleNodeFromDocument(GetServiceXPath(serviceName) + PrefixedSeparator + "issuerNameRegistry");
            IssuerNameRegistryElement element = null;

            if (node == null)
            {
                return null;
            }

            XmlAttribute namedItem = (XmlAttribute)node.Attributes.GetNamedItem("type");
            if (namedItem != null)
            {
                element = new IssuerNameRegistryElement(namedItem.Value);
            }

            if (element != null)
            {
                element.TrustedIssuers = this.ReadTrustedIssuers(serviceName);
            }

            return element;
        }

        public void WriteIssuerNameRegistry(IssuerNameRegistryElement issuerNameRegistry, string serviceName)
        {
            if (issuerNameRegistry == null)
            {
                throw new ArgumentNullException("issuerNameRegistry");
            }

            XmlElement newChild = this.CreateElementFromDocument("issuerNameRegistry");
            newChild.SetAttribute("type", issuerNameRegistry.Type);
            this.GetServiceNode(serviceName).AppendChild(newChild);
            
            if ((issuerNameRegistry.TrustedIssuers != null) && (issuerNameRegistry.TrustedIssuers.Count > 0))
            {
                this.WriteTrustedIssuer(issuerNameRegistry.TrustedIssuers, serviceName);
            }
        }

        public void UpdateIssuerNameRegistryElement(string serviceName, Collection<string> stsCertificatesThumbprints, string issuerName)
        {
            string formattedXPath;

            IssuerNameRegistryElement issuerNameRegistry = this.ReadIssuerNameRegistry(serviceName);
            if (serviceName == null)
            {
                formattedXPath = "/fed:configuration/fed:microsoft.identityModel/fed:service[count(@name)=0 or @name='']/fed:issuerNameRegistry";
            }
            else
            {
                formattedXPath = GetFormattedXPath("/fed:configuration/fed:microsoft.identityModel/fed:service[@name and @name='{0}']/fed:issuerNameRegistry", new string[] { serviceName });
            }

            if ((issuerNameRegistry != null) && StringComparer.Ordinal.Equals(issuerNameRegistry.Type, "Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"))
            {
                this.RemoveNode(formattedXPath);
            }
            else if (issuerNameRegistry != null)
            {
                issuerNameRegistry = null;
            }
            else
            {
                issuerNameRegistry = new IssuerNameRegistryElement("Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
            }

            if (issuerNameRegistry != null)
            {
                var collection = new Collection<TrustedIssuerElement>();
                foreach (TrustedIssuerElement element2 in issuerNameRegistry.TrustedIssuers)
                {
                    if (StringComparer.Ordinal.Equals(element2.Name, issuerName))
                    {
                        collection.Add(element2);
                    }
                }

                foreach (TrustedIssuerElement element3 in collection)
                {
                    issuerNameRegistry.TrustedIssuers.Remove(element3);
                }

                foreach (var certificateThumbprint in stsCertificatesThumbprints)
                {
                    bool flag = true;
                    foreach (TrustedIssuerElement element4 in issuerNameRegistry.TrustedIssuers)
                    {
                        if (StringComparer.OrdinalIgnoreCase.Equals(element4.Thumbprint.Replace(" ", string.Empty), certificateThumbprint.Replace(" ", string.Empty)))
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        issuerNameRegistry.TrustedIssuers.Add(new TrustedIssuerElement(certificateThumbprint, issuerName));
                    }
                }

                this.WriteIssuerNameRegistry(issuerNameRegistry, serviceName);
            }
        }

        public Collection<Uri> ReadAudienceUris(string serviceName)
        {
            XmlNode node = this.SelectSingleNodeFromDocument(GetServiceXPath(serviceName) + PrefixedSeparator + "audienceUris");
            if (node == null)
            {
                return null;
            }

            var collection = new Collection<Uri>();
            foreach (XmlNode node2 in node.ChildNodes)
            {
                XmlAttribute namedItem;
                if (StringComparer.Ordinal.Equals(node2.Name, "add"))
                {
                    namedItem = (XmlAttribute)node2.Attributes.GetNamedItem("value");
                    if (namedItem == null)
                    {
                        throw new ArgumentNullException("value");
                    }

                    collection.Add(new Uri(namedItem.Value));
                    continue;
                }

                if (StringComparer.Ordinal.Equals(node2.Name, "remove"))
                {
                    namedItem = (XmlAttribute)node2.Attributes.GetNamedItem("value");
                    if (namedItem == null)
                    {
                        throw new ArgumentNullException("value");
                    }

                    collection.Remove(new Uri(namedItem.Value));
                    continue;
                }

                if (StringComparer.Ordinal.Equals(node2.Name, "clear"))
                {
                    collection.Clear();
                }
            }

            return collection;
        }

        public void WriteAudienceUri(Collection<Uri> audienceUris, string serviceName)
        {
            if (audienceUris == null)
            {
                throw new ArgumentNullException("audienceUris");
            }

            foreach (Uri uri in audienceUris)
            {
                this.WriteAudienceUri(uri, serviceName);
            }
        }

        public void WriteAudienceUri(Uri audienceUri, string serviceName)
        {
            if (audienceUri == null)
            {
                throw new ArgumentNullException("audienceUri");
            }

            XmlElement newChild = this.CreateElementFromDocument("add");
            newChild.SetAttribute("value", audienceUri.AbsoluteUri);
            XmlNode node = this.SelectSingleNodeFromDocument(GetServiceXPath(serviceName) + PrefixedSeparator + "audienceUris");
            
            if (node == null)
            {
                node = this.CreateElementFromDocument("audienceUris");
            }

            this.GetServiceNode(serviceName).AppendChild(node).AppendChild(newChild);
        }

        public void WriteDisabledCertificateValidation(string serviceName)
        {
            XmlElement newChild = this.CreateElementFromDocument("certificateValidation");
            newChild.SetAttribute("certificateValidationMode", "None");
            string xPath = GetServiceXPath(serviceName) + PrefixedSeparator + "certificateValidation";
            XmlNode node = this.SelectSingleNodeFromDocument(xPath);
            XmlNode serviceNode = this.GetServiceNode(serviceName);
            
            if ((node != null) && !StringComparer.Ordinal.Equals(node.OuterXml, newChild.OuterXml))
            {
                // this.CommentNode(xPath, true);
                serviceNode.AppendChild(newChild);
            }
            else if (node == null)
            {
                serviceNode.AppendChild(newChild);
            }
        }

        public void WriteClaimsAuthenticationManager(string claimsAuthenticationManagerType, string serviceName)
        {
            XmlElement newChild = this.CreateElementFromDocument("claimsAuthenticationManager");
            newChild.SetAttribute("type", claimsAuthenticationManagerType);

            string xPath = GetServiceXPath(serviceName) + PrefixedSeparator + "claimsAuthenticationManager";
            XmlNode node = this.SelectSingleNodeFromDocument(xPath);
            XmlNode serviceNode = this.GetServiceNode(serviceName);

            if ((node != null) && !StringComparer.Ordinal.Equals(node.OuterXml, newChild.OuterXml))
            {
                serviceNode.AppendChild(newChild);
            }
            else if (node == null)
            {
                serviceNode.AppendChild(newChild);
            }
        }

        public bool RemoveNode(string xPath)
        {
            if (!string.IsNullOrEmpty(xPath))
            {
                XmlNodeList list = this.SelectNodesFromDocument(xPath);
                if (list != null)
                {
                    foreach (XmlNode node in list)
                    {
                        node.ParentNode.RemoveChild(node);
                    }

                    return true;
                }
            }

            return false;
        }

        public void FlushDocument()
        {
            XmlDocument document = new XmlDocument();
            document.Load(this.configurationFileLocation);
            
            if (!StringComparer.Ordinal.Equals(this.document.OuterXml, document.OuterXml))
            {
                // BackupFile(this.configurationFileLocation);
                var w = new XmlTextWriter(this.configurationFileLocation, Encoding.UTF8);
                w.Formatting = Formatting.Indented;
                this.document.WriteTo(w);
                w.Flush();
                w.Close();
            }
        }

        //private static void BackupFile(string fileName, int num = 1)
        //{   
        //    string path = string.Format(CultureInfo.InvariantCulture, "{0}.backup.{1}", new object[] { fileName, num });

        //    if (!File.Exists(path))
        //    {
        //        File.Copy(fileName, path);
        //    }
        //    else
        //    {
        //        num++;
        //        BackupFile(fileName, num);
        //    }
        //}

        private static string GetDefaultAttributeXPath(string attributeName)
        {
            return string.Format(CultureInfo.InvariantCulture, "[not({0}) or {0}='']", new object[] { attributeName });
        }

        private Collection<TrustedIssuerElement> ReadTrustedIssuers(string serviceName)
        {
            XmlNode node = this.SelectSingleNodeFromDocument(GetServiceXPath(serviceName) + PrefixedSeparator + "issuerNameRegistry" + PrefixedSeparator + "trustedIssuers");
            if (node == null)
            {
                return null;
            }

            var collection = new Collection<TrustedIssuerElement>();
            foreach (XmlNode node2 in node.ChildNodes)
            {
                XmlAttribute attribute;
                if (StringComparer.Ordinal.Equals(node2.Name, "add"))
                {
                    XmlAttribute namedItem = (XmlAttribute)node2.Attributes.GetNamedItem("name");
                    attribute = (XmlAttribute)node2.Attributes.GetNamedItem("thumbprint");
                    
                    if (namedItem == null)
                    {
                        throw new ArgumentNullException("name");
                    }

                    if (attribute == null)
                    {
                        throw new ArgumentNullException("thumbprint");
                    }

                    collection.Add(new TrustedIssuerElement(attribute.Value, namedItem.Value));
                    continue;
                }

                if (StringComparer.Ordinal.Equals(node2.Name, "remove"))
                {
                    attribute = (XmlAttribute)node2.Attributes.GetNamedItem("thumbprint");
                    if (attribute == null)
                    {
                        throw new ArgumentNullException("thumbprint");
                    }

                    for (int i = 0; i < collection.Count; i++)
                    {
                        if (StringComparer.Ordinal.Equals(collection[i].Thumbprint, attribute.Value))
                        {
                            collection.RemoveAt(i);
                        }
                    }

                    continue;
                }

                if (StringComparer.Ordinal.Equals(node2.Name, "clear"))
                {
                    collection.Clear();
                }
            }

            return collection;
        }

        private void WriteTrustedIssuer(Collection<TrustedIssuerElement> trustedIssuers, string serviceName)
        {
            if (trustedIssuers == null)
            {
                throw new ArgumentNullException("trustedIssuers");
            }

            foreach (TrustedIssuerElement element in trustedIssuers)
            {
                this.WriteTrustedIssuer(element, serviceName);
            }
        }

        private void WriteTrustedIssuer(TrustedIssuerElement trustedIssuer, string serviceName)
        {
            if (trustedIssuer == null)
            {
                throw new ArgumentNullException("trustedIssuer");
            }

            XmlElement newChild = this.CreateElementFromDocument("add");
            newChild.SetAttribute("thumbprint", trustedIssuer.Thumbprint);
            if (!string.IsNullOrEmpty(trustedIssuer.Name))
            {
                newChild.SetAttribute("name", trustedIssuer.Name);
            }

            XmlNode node = this.SelectSingleNodeFromDocument(GetServiceXPath(serviceName) + PrefixedSeparator + "issuerNameRegistry" + PrefixedSeparator + "trustedIssuers");
            if (node == null)
            {
                node = this.CreateElementFromDocument("trustedIssuers");
                this.SelectSingleNodeFromDocument(GetServiceXPath(serviceName) + PrefixedSeparator + "issuerNameRegistry").AppendChild(node);
            }

            node.AppendChild(newChild);
        }

        private XmlNodeList SelectNodesFromDocument(string xPath)
        {
            if (string.IsNullOrEmpty(xPath))
            {
                throw new ArgumentNullException("xPath");
            }

            return this.document.DocumentElement.SelectNodes(xPath, this.namespaceManager);
        }

        private XmlNode GetServiceNode(string serviceName)
        {
            XmlNode node = this.SelectSingleNodeFromDocument(GetServiceXPath(serviceName));
            if (node != null)
            {
                return node;
            }

            XmlNode node2 = this.WriteXPathNodes("/fed:configuration/fed:microsoft.identityModel");
            XmlElement newChild = this.CreateElementFromDocument("service");
            if (!string.IsNullOrEmpty(serviceName))
            {
                newChild.SetAttribute("name", serviceName);
            }

            node2.AppendChild(newChild);
            return newChild;
        }

        private XmlElement CreateElementFromDocument(string elementName)
        {
            if (string.IsNullOrEmpty(elementName))
            {
                throw new ArgumentNullException("elementName");
            }

            return this.document.CreateElement(elementName, this.document.DocumentElement.NamespaceURI);
        }

        private XmlNode WriteXPathNodes(string xPath)
        {
            if (string.IsNullOrEmpty(xPath))
            {
                throw new ArgumentNullException("xPath");
            }

            if (!xPath.StartsWith("/", StringComparison.Ordinal))
            {
                throw new FormatException("xPath");
            }

            string[] strArray = xPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            string str = string.Empty;
            XmlNode node = null;
            
            foreach (string str2 in strArray)
            {
                string elementName = str2;
                if (str2.StartsWith("fed:", StringComparison.Ordinal))
                {
                    elementName = str2.Replace("fed:", string.Empty);
                }

                str = str + PrefixedSeparator + elementName;
                
                XmlNode node3 = this.SelectSingleNodeFromDocument(str);
                if (node3 != null)
                {
                    node = node3;
                }
                else
                {
                    XmlNode newChild = this.CreateElementFromDocument(elementName);
                    if (node != null)
                    {
                        node.AppendChild(newChild);
                    }

                    node = newChild;
                }
            }

            return node;
        }

        private XmlNode SelectSingleNodeFromDocument(string xPath)
        {
            if (string.IsNullOrEmpty(xPath))
            {
                throw new ArgumentNullException("xPath");
            }

            return this.document.DocumentElement.SelectSingleNode(xPath, this.namespaceManager);
        }

        private WSFederationElement ReadWSFederation()
        {
            XmlNode node = this.SelectSingleNodeFromDocument("/fed:configuration/fed:microsoft.identityModel/fed:service[count(@name)=0 or @name='']/fed:federatedAuthentication/fed:wsFederation");
            if (node == null)
            {
                return null;
            }

            WSFederationElement element = null;
            XmlAttribute namedItem = (XmlAttribute)node.Attributes.GetNamedItem("issuer");
            XmlAttribute attribute2 = (XmlAttribute)node.Attributes.GetNamedItem("realm");
            
            if (namedItem == null)
            {
                throw new ArgumentNullException("issuer");
            }

            if (attribute2 == null)
            {
                throw new ArgumentNullException("realm");
            }
            
            element = new WSFederationElement(namedItem.Value, attribute2.Value);
            
            XmlAttribute attribute3 = (XmlAttribute)node.Attributes.GetNamedItem("passiveRedirectEnabled");
            if (attribute3 == null)
            {
                element.PassiveRedirectEnabled = false;
            }
            else
            {
                element.PassiveRedirectEnabled = XmlConvert.ToBoolean(attribute3.Value);
            }

            XmlAttribute attribute4 = (XmlAttribute)node.Attributes.GetNamedItem("freshness");
            if (attribute4 != null)
            {
                element.Freshness = new int?(XmlConvert.ToInt32(attribute4.Value));
            }

            XmlAttribute attribute5 = (XmlAttribute)node.Attributes.GetNamedItem("reply");
            if (attribute5 != null)
            {
                element.Reply = attribute5.Value;
            }

            XmlAttribute attribute6 = (XmlAttribute)node.Attributes.GetNamedItem("request");
            if (attribute6 != null)
            {
                element.Request = attribute6.Value;
            }

            XmlAttribute attribute7 = (XmlAttribute)node.Attributes.GetNamedItem("requestPtr");
            if (attribute7 != null)
            {
                element.RequestPtr = attribute7.Value;
            }

            XmlAttribute attribute8 = (XmlAttribute)node.Attributes.GetNamedItem("resource");
            if (attribute8 != null)
            {
                element.Resource = attribute8.Value;
            }

            XmlAttribute attribute9 = (XmlAttribute)node.Attributes.GetNamedItem("requireHttps");
            if (attribute9 != null)
            {
                element.RequireHttps = XmlConvert.ToBoolean(attribute9.Value);
            }

            XmlAttribute attribute10 = (XmlAttribute)node.Attributes.GetNamedItem("signInMode");
            if (attribute10 != null)
            {
                element.SignInMode = attribute10.Value;
            }

            XmlAttribute attribute11 = (XmlAttribute)node.Attributes.GetNamedItem("signInQueryString");
            if (attribute11 != null)
            {
                element.SignInQueryString = attribute11.Value;
            }

            XmlAttribute attribute12 = (XmlAttribute)node.Attributes.GetNamedItem("authenticationType");
            if (attribute12 != null)
            {
                element.AuthenticationType = attribute12.Value;
            }

            XmlAttribute attribute13 = (XmlAttribute)node.Attributes.GetNamedItem("homeRealm");
            if (attribute13 != null)
            {
                element.HomeRealm = attribute13.Value;
            }

            XmlAttribute attribute14 = (XmlAttribute)node.Attributes.GetNamedItem("policy");
            if (attribute14 != null)
            {
                element.Policy = attribute14.Value;
            }

            return element;
        }

        private void WriteWSFederation(WSFederationElement wsFederationElement)
        {
            if (wsFederationElement == null)
            {
                throw new ArgumentNullException("wsFederationElement");
            }
            if (string.IsNullOrEmpty(wsFederationElement.Issuer))
            {
                throw new ArgumentNullException("issuer");
            }
            if (string.IsNullOrEmpty(wsFederationElement.Realm))
            {
                throw new ArgumentNullException("realm");
            }
            
            XmlElement newChild = this.CreateElementFromDocument("wsFederation");
            if (wsFederationElement.PassiveRedirectEnabled)
            {
                newChild.SetAttribute("passiveRedirectEnabled", "true");
            }

            newChild.SetAttribute("issuer", wsFederationElement.Issuer);
            newChild.SetAttribute("realm", wsFederationElement.Realm);
            if (!string.IsNullOrEmpty(wsFederationElement.Reply))
            {
                newChild.SetAttribute("reply", wsFederationElement.Reply);
            }

            if (!string.IsNullOrEmpty(wsFederationElement.Request))
            {
                newChild.SetAttribute("request", wsFederationElement.Request);
            }

            if (wsFederationElement.Freshness.HasValue)
            {
                newChild.SetAttribute("freshness", XmlConvert.ToString(wsFederationElement.Freshness.Value));
            }

            if (!string.IsNullOrEmpty(wsFederationElement.RequestPtr))
            {
                newChild.SetAttribute("requestPtr", wsFederationElement.RequestPtr);
            }

            if (!string.IsNullOrEmpty(wsFederationElement.Resource))
            {
                newChild.SetAttribute("resource", wsFederationElement.Resource);
            }

            newChild.SetAttribute("requireHttps", XmlConvert.ToString(wsFederationElement.RequireHttps));
            if (!string.IsNullOrEmpty(wsFederationElement.SignInMode))
            {
                newChild.SetAttribute("signInMode", wsFederationElement.SignInMode);
            }

            if (!string.IsNullOrEmpty(wsFederationElement.SignInQueryString))
            {
                newChild.SetAttribute("signInQueryString", wsFederationElement.SignInQueryString);
            }

            if (!string.IsNullOrEmpty(wsFederationElement.AuthenticationType))
            {
                newChild.SetAttribute("authenticationType", wsFederationElement.AuthenticationType);
            }

            if (!string.IsNullOrEmpty(wsFederationElement.HomeRealm))
            {
                newChild.SetAttribute("homeRealm", wsFederationElement.HomeRealm);
            }

            if (!string.IsNullOrEmpty(wsFederationElement.Policy))
            {
                newChild.SetAttribute("policy", wsFederationElement.Policy);
            }
            
            this.WriteXPathNodes("/fed:configuration/fed:microsoft.identityModel/fed:service[count(@name)=0 or @name='']/fed:federatedAuthentication").AppendChild(newChild);
        }
    }
}